/*
 *  Cero Project - Copyright   2006 The Cero Developement Team 
 *  (Michael Laguerre, Camille Roux, Matthieu Segret, Mathieu Sivade) 
 * 
 *  This program is free software; you can redistribute it and/or modify it 
 *  under the terms of the GNU General Public License as published by the Free 
 *  Software Foundation; either version 2 of the License, or (at your option) 
 *  any later version.
 * 
 *  This program is distributed in the hope that it will be useful, but 
 *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
 *  for more details.
 */

package org.ceroproject.games;

import java.util.HashMap;
import java.util.Map;

import org.ceroproject.CeroException;
import org.ceroproject.ui.ChoiceMaker;
import org.ceroproject.ui.UserInterface;


/**
 * This class provides functions to access game perspectives. These perspectives
 * are the part of the game each player is able to see. When a game is created,
 * it must be passed to this class which will then bind GameInterfaces to the
 * shadows, thus preventing cheating.
 * 
 * @author Telem
 */
public class GameManager {

	/** The map of perspectives of the game, as seen by the players */
	private Map<Player, Game> perspectives = new HashMap<Player, Game>();

	/** The map of interfaces bound to the perspectives */
	private Map<Game, UserInterface> interfaces = new HashMap<Game, UserInterface>();

	/** The real game currently played */
	private Game currentGame;

	/**
	 * This constructor needs the real game to be passed in, though you could
	 * create shadows of a shadow. But I don't see the point xD
	 * 
	 * @param g
	 *            The real game to manage
	 * @throws NullPointerException
	 *             if g is null
	 */
	public GameManager(Game g) {
		if (g == null)
			throw new NullPointerException("The game can't be null");
		currentGame = g;
	}

	/**
	 * Binds the interface gi to the player p. The return value is most
	 * important and should be saved, as it will not be provided again later on.
	 * 
	 * @param p
	 *            The player which perspective is to get
	 * @param gi
	 *            The GameInterface which will represent this perspective
	 * @return The perspective of the game from p's point of view
	 * @throws CeroException
	 *             if an interface has already been defined for this player
	 */
	public Game setInterface(Player p, UserInterface gi) throws CeroException {
		if (interfaces.containsKey(perspectives.get(p)))
			throw new CeroException(
					"This player's interface is already defined");
		Game shadow = makeShadow(currentGame, p);
		perspectives.put(p, shadow);
		interfaces.put(shadow, gi);
		return shadow;
	}

	/**
	 * Returns the ChoiceMaker associated to this player
	 * 
	 * @param p
	 *            The player whose ChoiceMaker is needed
	 * @return The ChoiceMaker of p
	 * @throws CeroException
	 *             if p isn't known as a player of the game of this GameManager
	 */
	public ChoiceMaker getChoiceMaker(Player p) throws CeroException {
		if (!perspectives.containsKey(p))
			throw new CeroException("This player isn't registered in this game");
		return interfaces.get(perspectives.get(p)).getChoiceMaker();
	}

	/**
	 * This functions returns the shadow of a game, based on Player p's
	 * perspective. IE : he will not see other people's cards, so these cards
	 * won't be shown as such in the shadow, but as HiddenCards.
	 * 
	 * @param g
	 *            The Game which shadow is to make
	 * @param p
	 *            The Player which perspective is to use to create the shadow
	 * @return The shadow of Game g from the Player p's perspective
	 */
	protected Game makeShadow(Game g, Player p) {
		// TODO : dupliquage comme un porc par reflexivité ? Reste à réfléchir
		// sur les ID, si on les duplique ou les mappe.
		return null;
	}
}
